use tree;
use frag;
use geom;
use signal;

use super::core::{
  GUI, GUIContext, DynComponent,
};

////////////////////////////////////////////////////////////////////////////////////////////////////
// GUI live+underlying tree

pub struct LiveGUI {
  size: geom::Dim,
  live: tree::Live<DynComponent, <DynComponent as tree::Abstract>::State>,
  frag: frag::Frag,
  evt_dispatch: signal::EvtDispatcherPtr,
}

impl LiveGUI {

  pub fn new(size: geom::Dim, app: GUI) -> LiveGUI {
    let mut ui = LiveGUI {
      size,
      live: tree::Live::frag(),
      frag: frag::Frag::default(),
      evt_dispatch: signal::EvtDispatcher::new().into_rc_ptr(),
    };

    {
      // impose the initial tree
      let mut base_ctx = GUIContext::with_dispatcher(ui.evt_dispatch.clone());
      ui.live.impose(app.0, &mut ui.frag, &mut base_ctx);
      ui.recalc();
      assert_eq!(base_ctx.path.len(), 0);
    }

    ui
  }

  pub fn root_frag(&self) -> &frag::Frag { &self.frag }

  pub fn set_size(&mut self, size: geom::Dim) {
    self.size = size;
    self.recalc();
  }

  pub fn fire_click_evt(&mut self, pos: geom::Pos) {
    for fevt in self.frag.fire_click_evt(pos) {
      fevt.dispatch(&self.live, &self.evt_dispatch)
    }
  }

  fn recalc(&mut self) {
    self.frag.calculate_geometry(self.size);
  }
}
